package proxy03;

import org.junit.Test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * 动态代理实现AOP:
 *   动态指的是:在程序运行时,由JVM为我们自动生成代理类(隐式代理)
 *
 * 用到的Class类中的方法:
 *    ClassLoader getClassLoader()
 *           返回该类的类加载器。
 *
 *    Class<?>[] getInterfaces()
 *           确定此对象所表示的类或接口实现的接口。
 *
 * 我们需要通过Proxy类的方法来实现动态代理
 *   static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
 *           返回一个指定接口的代理类实例，该接口可以将方法调用指派到指定的调用处理程序。
 *
 *   第一个参数:传递一个类加载器,用来加载JVM生成的代理类,我们一般使用和被代理类(老王类)相同的加载器
 *   第二个参数:传递代理类和被代理类实现的接口(一个类实现的接口有可能多个,所以用数组接收)
 *   第三个参数:传递一个InvocationHandler接口实现类对象,InvocationHandler实现类对象绑定在代理类对象上
 *   返回值:底层会返回由JVM生成的代理类的一个实例
 *
 *   JVM隐式生成的代理类:
 *     class $Proxy1 implements OneDay{
 *         public void eat(){
 *
 *         }
 *         public void play(){
 *
 *
 *         }
 *         public void sleep(){
 *
 *         }
 *     }
 */
public class Demo {
	@Test
	public void testProxy() {
		//1.传递一个类加载器
		ClassLoader cl = LaoWang.class.getClassLoader();

		//2.代理类和被代理类实现的接口
		Class<?>[] interfaces = LaoWang.class.getInterfaces();

		//3.创建InvocationHandler实现类对象
		InvocationHandler ih = new HandlerImpl();

		//4.调用 newProxyInstance()方法
		OneDay od = (OneDay) Proxy.newProxyInstance(cl, interfaces, ih);//OneDay接口指向底层代理类对象,底层代理类实现OneDay接口
		                                                               //多态形式
		od.eat(); //通过代理类对象调用的方法最终都被转调传递的InvocationHandler实现类的invoke方法
		System.out.println("------------");
		od.sleep();
		System.out.println("------------");
		od.play();

	}
}
